﻿using DAEProde.Domain;
using DAEProde.Tasks.ViewModels;
using SharpLite.Domain.DataInterfaces;
using System.Linq;
using System.Collections.Generic;
using System;
using DAEProde.Domain.Validators;

namespace DAEProde.Tasks
{
    public class MatchDateCudTasks : BaseEntityCudTasks<MatchDate, EditMatchDateViewModel>
    {
        private readonly IRepository<Tournament> _tournamentRepository;
        private readonly IRepository<MatchDate> _matchDateRepository;

        public MatchDateCudTasks(IRepository<MatchDate> matchDateRepository, IRepository<Tournament> tournamentRepository)
            : base(matchDateRepository) { _matchDateRepository = matchDateRepository; _tournamentRepository = tournamentRepository; }

        protected override void TransferFormValuesTo(MatchDate toUpdate, MatchDate fromForm)
        {
            toUpdate.Name = fromForm.Name;
            toUpdate.Tournament = fromForm.Tournament;
            toUpdate.Date = fromForm.Date;
        }

        public virtual ActionConfirmation<MatchDate> SaveResults(string[] fromForm, int id)
        {
            if (fromForm == null) throw new ArgumentNullException("fromForm may not be null");
            if (!DataAnnotationsValidator.TryValidate(fromForm)) throw new InvalidOperationException("fromForm is in an invalid state");


            // But if the ID of fromForm is > 0, then we know we're updating an existing one.
            // Always update the existing one instead of simply "updating" the item from the form.  Otherwise,
            // you risk the loss of important data, such as references not captured by the form or audit 
            // details that exists from when the object was initially saved.
            MatchDate toUpdate = _matchDateRepository.Get(id);

            int aux = 0;
            foreach (var r in fromForm)
            {
                toUpdate.Matches.ElementAt(aux).Result = r;
                aux++;
            }

            foreach (var t in toUpdate.Tickets)
            {
                var sum = 0;
                foreach (var p in t.Predictions)
                {
                    if (p.Will.Equals(p.Match.Result))
                    {
                        sum++;
                    }
                }
                t.MatchDateScore = sum;
            }

            // Since any changes will be automatically persisted to the DB when the current transaction
            // is committed, we want to make sure it's in a valid state after being updated.  If it's 
            // not, it's most likely a development bug. In design-by-contract speak, this is an "ensure check."
            if (!DataAnnotationsValidator.TryValidate(toUpdate))
                throw new InvalidOperationException("The " + GetFriendlyNameOfType() + " could not be updated due to missing or invalid information");

            return ActionConfirmation<MatchDate>.CreateSuccessConfirmation(
                "The " + GetFriendlyNameOfType() + " was successfully updated.", toUpdate);
        }

        // Construccion basica del view model que inicializa lista de torneos para el dropdown
        public override EditMatchDateViewModel CreateEditViewModel()
        {
            var viewModel = base.CreateEditViewModel();

            // Esto sera mostrado por la vista para seleccionar un torneo
            viewModel.AvaileableTournaments = _tournamentRepository.GetAll().OrderBy(pc => pc.Name);

            return viewModel;
        }

        public EditMatchDateViewModel CreateViewModel(int tId)
        {
            var viewModel = CreateEditViewModel(tId);

            var tournament = _tournamentRepository.Get(tId);

            viewModel.AvaileableTournaments = viewModel.AvaileableTournaments.Where(x => x.Equals(tournament));

            viewModel.MatchDate = new MatchDate();
            viewModel.MatchDate.Tournament = tournament;

            return viewModel;
        }
    }
}
